-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[Clang][CodeGen] Bail out on constexpr unknown values in ConstantEmitter #127525
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Yingwei Zheng (dtcxzyw) ChangesAfter #95474, unknown references are valid in constant expressions. However, constexpr-unknown values are not allowed in CodeGen. This patch bails out on constexpr-unknown values to ensure the load of reference is emitted. Close #127475 Full diff: https://github.com/llvm/llvm-project/pull/127525.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index ee5874b26f534..075f3f435ad74 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1883,8 +1883,10 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
// Try to emit the initializer. Note that this can allow some things that
// are not allowed by tryEmitPrivateForMemory alone.
- if (APValue *value = D.evaluateValue())
- return tryEmitPrivateForMemory(*value, destType);
+ if (APValue *value = D.evaluateValue()) {
+ if (!value->allowConstexprUnknown())
+ return tryEmitPrivateForMemory(*value, destType);
+ }
return nullptr;
}
diff --git a/clang/test/CodeGenCXX/cxx23-p2280r4.cpp b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp
new file mode 100644
index 0000000000000..d5409be451df0
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -emit-llvm -o - | FileCheck %s
+
+extern int& s;
+
+// CHECK: @_Z4testv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[I:%.*]] = alloca ptr, align {{.*}}
+// CHECK-NEXT: [[X:%.*]] = load ptr, ptr @s, align {{.*}}
+// CHECK-NEXT: store ptr [[X]], ptr [[I]], align {{.*}}
+int& test() {
+ auto &i = s;
+ return i;
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo nit.
No changelog needed, this sould be backported to clang 20, it's a fairly severe regression.
I wonder if there are other places where we let constexpr-unknown references escapes and if there are cases where they should not be formed to begin with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the change is correct, but I've added the codegen code owners for another set of eyes. This seems like something we should try to get into 20.x as it's fixing a regression (miscompilation, at that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it even make sense for evaluateValue to return a constexpr-unknown value? If I'm following correctly, we can't actually do anything useful with such a result: we don't actually know what the value is. It would make things simpler if we kept such APValues as an internal implementation detail of ExprConstant.
Clang rejects the following case after modifying
|
I don't see the connection. At least, there isn't any obvious connection: the testcase doesn't require constexpr-unknown. Maybe you need to "reject" the value earlier? |
See #128409. I have made some attempts but still cannot fix the test failure. |
How do people feel about landing and backporting this as a stop-gap solution for clang 20 while we investigate whether a cleaner design can be found in trunk? |
I'm worried this is just scratching the surface... it looks like there's a whole class of issues involving constexpr-unknown leaking out of constant evaluation, and this is just addressing one specific case. If we can't take #128409 on the branch, we should just disable the feature and give it more time to bake on main. |
Can I suggest adding this to the 20.X milestone to bring more attention to it so it goes through before the release? clang is quite unusable at the moment because of this |
I think it would be a shame to lose the feature, it is incredibly useful. I looked at #128409 and don't have any problems with it, we could definitely cherry pick it. That said, this patch might be worth having in that branch AS WELL to cover any other missed cases. I would be OK having this patch HERE only on that branch or replaced with an assert in main. |
Closed in favor of #128409 |
…ateAsInitializer` (#128409) It is an alternative to llvm/llvm-project#127525. Close llvm/llvm-project#127475.
#128409 should cover all the cases this patch would cover. I'm a little concerned #128409 still isn't broad enough... but not in a way that would trigger this check. I'll continue discussion there. |
…lizer` (llvm#128409) It is an alternative to llvm#127525. Close llvm#127475.
…lizer` (#128409) It is an alternative to llvm/llvm-project#127525. Close llvm/llvm-project#127475.
…lizer` (llvm#128409) It is an alternative to llvm#127525. Close llvm#127475.
After #95474, unknown references are valid in constant expressions. However, constexpr-unknown values are not allowed in CodeGen. This patch bails out on constexpr-unknown values to ensure the load of reference is emitted.
Close #127475